package core.component.auth;

import com.distribute.pojo.LoginInfo;
import com.distribute.pojo.Result;
import com.distribute.utils.JsonUtils;
import config.DSConfig;
import constant.DSConstants;
import core.api.AuthManager;
import exception.ApiException;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;

public class SessionAuthenticator implements Authenticator, AuthManager {

    private final OkHttpClient okHttpClient;

    private final DSConfig dsConfig;

    private final ReentrantLock sessionLock = new ReentrantLock();

    public SessionAuthenticator(DSConfig dsConfig){
        this.okHttpClient = new OkHttpClient();
        this.dsConfig = dsConfig;
    }
    @Nullable
    @Override
    public Request authenticate(@Nullable Route route, @NotNull Response response) throws IOException {
        if(response.code() != 401){
            return null;
        }

        // 获取新的登录信息
        LoginInfo login = login();

        return response.request().newBuilder()
                .header(DSConstants.SESSION_ID,login.getSessionId())
                .addHeader(DSConstants.COOKIE,String.format(DSConstants.COOKIE_INFO,login.getSecurityConfigType(),login.getSessionId(),login.getSessionId()))
                .build();
    }

    @Override
    public LoginInfo login() {
        String oldSessionId = LoginInfoHolder.getInstance(dsConfig.getUserName()).getSessionId();

        sessionLock.lock();
        // 表示有人更新过
        if(!Objects.equals(oldSessionId, LoginInfoHolder.getInstance(dsConfig.getUserName()).getSessionId())){
            return LoginInfoHolder.getInstance(dsConfig.getUserName());
        }
        // 构建表单数据
        FormBody formBody = new FormBody.Builder()
                .add(DSConstants.USER_NAME, dsConfig.getUserName())
                .add(DSConstants.USER_PASSWORD, dsConfig.getUserPassword())
                .build();

        // 构建登录请求
        String url = buildUrl(DSConstants.LOGIN);
        Request loginRequest = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        try (Response response = okHttpClient.newCall(loginRequest).execute()){
            String body = response.body().string();
            Result result = JsonUtils.toBean(body,Result.class);
            if(result.isFailed()){
                throw new ApiException("auth failed");
            }

            LoginInfo login = JsonUtils.toBean(result.getData(), LoginInfo.class);
            // 更新全局登录信息
            LoginInfoHolder.getInstance(dsConfig.getUserName()).setSessionId(login.getSessionId());
            LoginInfoHolder.getInstance(dsConfig.getUserName()).setSecurityConfigType(login.getSecurityConfigType());
            LoginInfoHolder.getInstance(dsConfig.getUserName()).setUserName(dsConfig.getUserName());
            return LoginInfoHolder.getInstance(dsConfig.getUserName());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            sessionLock.unlock();
        }
    }

    /**
     * 构建路径
     *
     * @param path
     * @param uriVariables
     * @return
     */
    private String buildUrl(String path, Object... uriVariables) {
        path = StringUtils.removeStart(path, "/");
        return "http://" + dsConfig.getUrl() + "/" + DSConstants.DS + "/" + String.format(path, uriVariables);
    }

    @Override
    public boolean signOut() {
        return false;
    }

    @Override
    public LoginInfo getLoginInfo() {
        return LoginInfoHolder.getInstance(dsConfig.getUserName());
    }
}
